# -*- coding: utf-8 -*-
'''
Created on 31/01/2010

@author: joger
'''

import wx
import pexpect
import os
import re

from imagenes import images
from comun import mensageError as msje, mensageAlerta as msja

class Modelo():
    '''
    classdocs
    '''
    
    def __init__(self,controlador):
        '''
        Constructor
        '''
        self.separador_titulo = "|_|"
        self.diccionarioDatos = {}
        self.rutaBD = controlador.home + controlador.rutaBD
        self.controlador = controlador
        #Procedemos a conectarnos a la base de datos de los password
    
    def listarContrasegnas(self):
        
        self.diccionarioDatos = {} 
        
        datos = self.listarPorCategoria(self.controlador.vista.tree.GetItemText(self.controlador.vista.treePresionado).encode('utf8'))
        
        for i in range(len(datos)):
            #print 'L: 37 modelo.py. pwsafe -f "%s" -lupE "%s"' % (self.controlador.db,datos[i])
            #f = open("/home/joger/Escritorio/ttt.txt","a")
            #f.write(datos[i])
            #f.close()
            #print 'L: 37 modelo.py. %s' % datos[i]
            #print 'pwsafe -f "%s" -lupE "%s"' % (self.controlador.db,datos[i].strip().decode('utf8'))
            proceso = pexpect.spawn('pwsafe -f "%s" -lupE "%s"' % (self.controlador.db,datos[i].strip().decode('utf8')))
            options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
            resultado = proceso.expect(options,timeout=5)
            
            if resultado == 0:
                proceso.sendline(self.controlador.password)
                try:
                    lineas = proceso.readlines()
                    #print len(lineas)
                    longitud = len(lineas)
                    #Este caso ocurre cuando la clave no tiene observaciones
                    if longitud == 3:
                        #self.diccionarioDatos[i] = (datos[i].split(".")[1].strip(),lineas[1].strip().replace("username for " + datos[i].strip() + ": ",""),"******","",lineas[2].strip().replace("password for " + datos[i].strip() + ": ",""))
                        self.diccionarioDatos[i] = (datos[i].strip()[datos[i].strip().find('.')+1:].replace(self.separador_titulo,"."),lineas[1].strip().replace("username for " + datos[i].strip() + ": ",""),"******","",lineas[2].strip().replace("password for " + datos[i].strip() + ": ",""))
                    ##Este caso ocurre cuendo la clave tiene observaciones
                    elif longitud == 4: 
                        #self.diccionarioDatos[i] = (datos[i].split(".")[1].strip(),lineas[1].strip().replace("username for " + datos[i].strip() + ": ",""),"******",lineas[3].strip().replace("> ",""),lineas[2].strip().replace("password for " + datos[i].strip() + ": ",""))
                        self.diccionarioDatos[i] = (datos[i].strip()[datos[i].strip().find('.')+1:].replace(self.separador_titulo,"."),lineas[1].strip().replace("username for " + datos[i].strip() + ": ",""),"******",lineas[3].strip().replace("> ",""),lineas[2].strip().replace("password for " + datos[i].strip() + ": ",""))
                except:
                    self.controlador.vista.txtPanelC.SetLabel(str(proceso.after) + " Esto")
                    msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
                    return False

            else:
                self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
                msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
                return False
              
        #diccionarioDatos[0] = ("Titulo","","Usuario","Clave","Comentarios",)
        #diccionarioDatos[1] = ("Celda 6","Celda 7","Celda 8","Celda 9","Celda 10",)
        
        #return self.diccionarioDatos
        #print self.diccionarioDatos
    
    def listarCategorias(self,nombre,clave):
        #Se buscan las categorías en la base de datos y se devuelve una lista
        categorias = []
        #Procedemos a abrir la base de datos
        db =  self.rutaBD + nombre + ".dat"
        proceso = pexpect.spawn('pwsafe -f "%s" --list' % db)
        options= ["Enter passphrase for "+ str(db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect(options,timeout=5)
        if resultado == 0:
            proceso.sendline(clave)
            proceso.terminate(force=True)
            lineas = proceso.readlines()
            if len(lineas) > 1 and lineas[1] == 'Passphrase is incorrect\r\n':
                self.controlador.vista.txtPanelC.SetLabel(u"¡Clave incorrecta!")
                msje(self.controlador.vista.ventanaHija,u"¡Clave incorrecta!")
                return False
            else:
                categorias = []
                for l in lineas:
                    if l == "\r\n":
                        continue
                    
                    l1 = l.split(".")
                    try:
                        categorias.index(l1[0])
                    except ValueError:
                        categorias.append(l1[0])
                
                self.controlador.nombreBD = nombre 
                self.controlador.db = db
                self.controlador.password = clave
                self.controlador.habilitarCerrarBD(True)
                self.controlador.habilitarAnhadirG(True)
                
                return categorias
            """
            try:
                lineas = proceso.readlines()
               
                for l in lineas:
                    l1 = l.split(".")
                    if l1[0] == "\r\n":
                        continue
                    try:
                        categorias.index(l1[0])
                    except ValueError:
                        categorias.append(l1[0])
                
                
            
                self.controlador.nombreBD = nombre 
                self.controlador.db = db
                self.controlador.password = clave
                self.controlador.habilitarCerrarBD(True)
                self.controlador.habilitarAnhadirG(True)
            
            except:
                self.controlador.vista.txtPanelC.SetLabel("Error al conectarse a la base de datos. La clave es incorrecta")
                msje(self.controlador.vista.ventanaHija,"Error al conectarse a la base de datos. La clave es incorrecta")
            """
                
            #Procedemos a almacenar el password, usuario y nombre de la BD
            
            
        else:
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte iinferior de la aplicación y consulte al administrador del sistema")
            return False
    
    #def abrirBD(self,nombre,clave):
        
    
        
    def crearBaseDatos(self,nombre,clave):
        
        #Procedemos a crear la base de datos
        db = self.rutaBD + nombre + ".dat"
        proceso = pexpect.spawn('pwsafe -f "%s" --createdb' % db)
        #pregunta = 
        options= ["Enter passphrase for "+ str(db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        
        resultado = proceso.expect(options,timeout=5)
        
        if resultado == 0:
            proceso.sendline(clave)
            proceso.expect('Reenter passphrase for '+ str(db) +': ')
            proceso.sendline(clave)
            #Procedemos a almacenar el password y usuario
            self.controlador.nombreBD = nombre
            self.controlador.db = db
            self.controlador.password = clave
            return True
        else:
            #Imprimimos los errores ocurridos en el la parte inferior de la ventana
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            return False
    
    def listarBD(self):
        bd = ['--Seleccione--']
        try:
            bd+= [f.split(".")[0] for f in os.listdir(self.rutaBD) if os.path.isfile(os.path.join(self.rutaBD, f)) and f[0] != "." and not re.match(".*~$",f)]
            
        except OSError:
            self.controlador.vista.txtPanelC.SetLabel("Error: No se pudo leer el fichero " + self.rutaBD +  ". Consulte con el administrador del sistema")
            
        
        return bd
            
    def listarPorCategoria(self,categoria):
        
        categorias = []
        #print 'pwsafe -f "%s" --list "%s"' % (self.controlador.db,categoria.decode("utf8"))
        proceso = pexpect.spawn('pwsafe -f "%s" --list "%s"' % (self.controlador.db,categoria.decode("utf8")))
        
        options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect(options,timeout=5)
        if resultado == 0:
            proceso.sendline(self.controlador.password)
            try:
                lineas = proceso.readlines()
                for l in lineas:
                    if l != "\r\n":
                        
                        categorias.append(l)
            except:
                self.controlador.vista.txtPanelC.SetLabel("Error al conectarse a la base de datos. La clave es incorrecta")
                msje(self.controlador.vista.ventanaHija,"Error al conectarse a la base de datos. La clave es incorrecta")
            #Procedemos a almacenar el password, usuario y nombre de la BD
            
            
        else:
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte iinferior de la aplicación y consulte al administrador del sistema")
            
        
        return categorias
    
    def editarCategoria(self,categoria,nuevaCategoria):
        
        listaC = self.listarPorCategoria(categoria)
        #print listaC
        for c in listaC:
            #print c
            #proceso = pexpect.spawn("pwsafe -f " + self.controlador.db + " -e " + c)
            proceso = pexpect.spawn('pwsafe -f "%s" -e "%s"' % (self.controlador.db,c.strip()))
            #options= ["Enter passphrase for "+ str(self.controlador.db) +": ","notes: [<keep same>] ","Confirm changing group, name ? [y]",pexpect.TIMEOUT, pexpect.EOF]
            resultado = proceso.expect("Enter passphrase for "+ str(self.controlador.db) +": ",timeout=5)
            #Obtenemos el grupo y la clave en un array
            #grupoClave = c.split(".")
            if resultado == 0:
                
                proceso.sendline(self.controlador.password)
                proceso.expect("name: *",timeout=5)
                proceso.sendline("")
                proceso.expect("group: *",timeout=5)
                proceso.sendline(nuevaCategoria)
                proceso.expect("username: *",timeout=5)
                proceso.sendline("")
                proceso.expect("change password *",timeout=5)
                proceso.sendline("n")
                proceso.expect("notes: *",timeout=5)
                proceso.sendline("")
                proceso.expect("Confirm changing *",timeout=5)
                proceso.sendline("y")
            else:
                self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
                msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte iinferior de la aplicación y consulte al administrador del sistema")
                break
            
    def buscarClave(self,entrada):
        
        #print 'pwsafe -f  "%s" --list "%s"' % (self.controlador.db,entrada)
        proceso = pexpect.spawn('pwsafe -f  "%s" --list "%s"' % (self.controlador.db,entrada))
        #options= ["Enter passphrase for "+ str(self.controlador.db) +": ","notes: [<keep same>] ","Confirm changing group, name ? [y]",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect("Enter passphrase for "+ str(self.controlador.db) +": ",timeout=5)
        #Obtenemos el grupo y la clave en un array
        #grupoClave = c.split(".")
        if resultado == 0:
            proceso.sendline(self.controlador.password)
            lineas = proceso.readlines()
            for l in lineas:
                #print "Linea: " + l 
                if l != "\r\n":
                    #print 'buscarClave'
                    return True
        #print 'buscarClave'    
        return False    
    
    def eliminarCategoria(self):
        
        #Obtenemos una lista con todos las entradas a eliminar
        datos = self.listarPorCategoria(self.controlador.vista.tree.GetItemText(self.controlador.vista.treePresionado))
        
        for c in datos:
            #Limpiamos a c de los saltos de lineas
            categoria = c.strip()
            #print "**" + categoria + "**"
            proceso = pexpect.spawn('pwsafe -f "%s" --delete "%s"' % (self.controlador.db,categoria))
            options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
            resultado = proceso.expect(options,timeout=5)
            #Obtenemos el grupo y la clave en un array
            #grupoClave = c.split(".")
            if resultado == 0:
                proceso.sendline(self.controlador.password)
            else:
                self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
                msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte iinferior de la aplicación y consulte al administrador del sistema")
                return False
        
        return True
    
    def ingresarClave(self,categoria,titulo,usuario,clave,comentario):
        
        #Es necesario remplazar todos los puntos que tenga el titulo por el caracter de remplazo de puntos que
        #es una varaible de esta clase. Esto se debe a que pwsafe interpreta los puntos del titulo como categorias,
        #es decir:
        #pwsafe -f "/home/joger/.tibisay/dbclaves/bd1.dat" -a "gmail.com"
        #El comando de arriba crearía un grupo gmail donde su titulo de clave sería
        #com . Pero lo que se busca es que gmail.com sea un titulo. La variable categoria
        #almacenaría la categoria de ese titulo
        titulo = titulo.replace(".",self.separador_titulo)
        #
        #p = re.compile(".")
        #p.findall(titulo)
        #print 'pwsafe -f "%s" -a "%s"' % (self.controlador.db,titulo)
        #print categoria.encode('utf8')
        #return False
        #proceso = pexpect.spawn('pwsafe -f "%s" -a "%s"' % (self.controlador.db,titulo))
        entrada = categoria.encode('utf8') + "." + titulo.encode("utf8")
        #print 'pwsafe -f "%s" -a "%s"' % (self.controlador.db,entrada)
        #return 
        proceso = pexpect.spawn('pwsafe -f "%s" -a "%s"' % (self.controlador.db,entrada))
        options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect(options,timeout=5)
        #Obtenemos el grupo y la clave en un array
        #grupoClave = c.split(".")
        if resultado == 0:
            try:
                proceso.sendline(self.controlador.password)
                #proceso.expect("group *",timeout=5)
                #proceso.sendline(categoria.encode('utf8'))
                proceso.expect("username: ",timeout=5)
                #print '259 modelo.py: ' + usuario
                proceso.sendline(usuario.encode('utf8'))
                proceso.expect("password *",timeout=5) 
                proceso.sendline(clave.encode('utf8'))
                proceso.expect("password again: ",timeout=5) 
                proceso.sendline(clave.encode('utf8'))
                proceso.expect("notes: ",timeout=5)
                proceso.sendline(comentario.encode('utf8'))
            except:
                self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
                msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
                        
        else:
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
            return False
        
        return True
        
    def modificarClave(self,categoria,tituloOriginal,titulo,usuario,clave,comentario):
        #print "pwsafe -f " + self.controlador.db + " -e " + categoria + "." + titulo
        #proceso = pexpect.spawn("pwsafe -f " + self.controlador.db + " -e " + categoria + "." + tituloOriginal)
        
        #En el cado del titulo tener puntos se debe remplazar por la variable self.separador_titulo. La razón de este
        #remplazo se debe a que pwsafe no dejaba alamcer titulos como este:
        #gmail.com
        #ya que cuando se hacía eso pwsafe asumía que gmail era la categoría
        titulo = titulo.replace(".",self.separador_titulo)
        tituloOriginal = tituloOriginal.replace(".",self.separador_titulo)
        #print 'pwsafe -f "%s" -e "%s.%s"' % (self.controlador.db,categoria,tituloOriginal)
        #return 
        proceso = pexpect.spawn('pwsafe -f "%s" -e "%s.%s"' % (self.controlador.db,categoria,tituloOriginal))
        options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect(options,timeout=5)
        #Obtenemos el grupo y la clave en un array
        #grupoClave = c.split(".")
        if resultado == 0:
            try:
            #if 1:
                proceso.sendline(self.controlador.password)
                proceso.expect("name *",timeout=5)
                proceso.sendline(titulo.encode('utf8'))
                proceso.expect("group *",timeout=5)
                proceso.sendline(categoria.encode('utf8'))
                proceso.expect("username:*",timeout=5)
                proceso.sendline(usuario.encode('utf8'))
                proceso.expect("change password *",timeout=5) 
                proceso.send("y")
                proceso.expect("new password: *",timeout=5)
                proceso.sendline(clave.encode('utf8'))
                proceso.expect("new password again: *",timeout=5) 
                proceso.sendline(clave.encode('utf8'))
                proceso.expect("notes: *",timeout=5) 
                proceso.sendline(comentario.encode('utf8'))
                #print proceso.readlines()
                proceso.expect("Confirm changing *",timeout=5) 
                proceso.sendline("y")
                
            except pexpect.EOF:
                self.controlador.vista.txtPanelC.SetLabel("¡No ocurrieron cambios en los datos!")
            
            except:
                #print proceso.logfile_read
                self.controlador.vista.txtPanelC.SetLabel(str(proceso.before) + str(proceso.after))
                msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! Lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
                return False
                        
        else:
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
            return False
        
        return True
    
    
    def eliminarClave(self,categoria,titulo):
        
        #En el cado del titulo tener puntos se debe remplazar por la variable self.separador_titulo. La razón de este
        #remplazo se debe a que pwsafe no dejaba alamcer titulos como este:
        #gmail.com
        #ya que cuando se hacía eso pwsafe asumía que gmail era la categoría
        titulo = titulo.replace(".",self.separador_titulo)
        #proceso = pexpect.spawn("pwsafe -f " + self.controlador.db + " --delete " + categoria + "." + titulo)
        proceso = pexpect.spawn('pwsafe -f "%s" --delete "%s.%s"' % (self.controlador.db,categoria,titulo))
        options= ["Enter passphrase for "+ str(self.controlador.db) +": ",pexpect.TIMEOUT, pexpect.EOF]
        resultado = proceso.expect(options,timeout=5)
        #Obtenemos el grupo y la clave en un array
        #grupoClave = c.split(".")
        if resultado == 0:
            proceso.sendline(self.controlador.password)
        else:
            self.controlador.vista.txtPanelC.SetLabel(str(proceso.before))
            msje(self.controlador.vista.ventanaHija,"¡Ocurrio un error inesperado! lea la información en la parte inferior de la aplicación y consulte al administrador del sistema")
            return False
        
        return True
